#pragma once;
#include "Events.h"
#include "Object.h"

class Application : public Object
{
public:
    Application( const std::string& name, int width = 1280, int height = 720 );
    virtual ~Application();

    // Run the application
    // Will return error code.
    virtual int Run();
    // Stop the app from running and close the application window.
    virtual void Stop();

    // At the end of the render, we should invoke this method to ensure
    // the contents of the back buffer are presented to the screen.
    virtual void Present();

    // Get the width,height of the application window in pixels.
    glm::ivec2 GetWindowDimensions() const;
    int GetWindowWidth() const;
    int GetWindowHeight() const;


    // Window events
    Event           InputFocus;
    Event           InputBlur;
    Event           MouseFocus;
    Event           MouseBlur;
    Event           Minimize;
    Event           Restore;
    ResizeEvent     Resize;
    Event           Expose;
    Event           Exit;

    // Application execution events
    Event           Initialized;
    UpdateEvent     Update;
    RenderEvent     Render;
    Event           Terminated;

    // Keyboard events
    KeyboardEvent   KeyPressed;
    KeyboardEvent   KeyReleased;

    // Mouse events
    MouseMotionEvent MouseMoved;
    MouseButtonEvent MouseButtonPressed;
    MouseButtonEvent MouseButtonReleased;

    // User events
    UserEvent        UserEvent;

protected:

    virtual bool Initialize();
    virtual void Terminate();

    // The application has been successfully initialized.
    virtual void OnInitialized( EventArgs& e );
    virtual void OnUpdate( UpdateEventArgs& e );
    virtual void OnRender( RenderEventArgs& e );
    // The application instance has been terminated.
    virtual void OnTerminated( EventArgs& e );

    // The generic event handler will dispatch events to the proper
    // event handlers
    virtual void EventHandler( SDL_Event& event );

    // The application window has received focus
    virtual void OnInputFocus( EventArgs& e );
    // The application window has lost focus
    virtual void OnInputBlur( EventArgs& e );

    // The application window has received mouse focus
    virtual void OnMouseFocus( EventArgs& e );
    // The application window has lost mouse focus
    virtual void OnMouseBlur( EventArgs& e );

    // The application window has been minimized
    virtual void OnMinimize( EventArgs& e );
    // The application window has been restored
    virtual void OnRestore( EventArgs& e );

    // A keyboard key was pressed
    virtual void OnKeyPressed( KeyEventArgs& e );
    // A keyboard key was released
    virtual void OnKeyReleased( KeyEventArgs& e );
    // The mouse was moved
    virtual void OnMouseMoved( MouseMotionEventArgs& e );
    // A button on the mouse was pressed
    virtual void OnMouseButtonPressed( MouseButtonEventArgs& e );
    // A button on the mouse was released
    virtual void OnMouseButtonReleased( MouseButtonEventArgs& e );
    
    // The application window has be resized
    virtual void OnResize( ResizeEventArgs& e );
    // The window contents should be repainted
    virtual void OnExpose( EventArgs& e );
    
    // The user requested to exit the application
    virtual void OnExit( EventArgs& e );

    // A user event was generated in the SDL message queue.
    virtual void OnUserEvent( UserEventArgs& e );
private:

    std::string     m_ApplicationName;
    bool            m_bIsInitialized;
    bool            m_bIsRunning;

    int             m_iWindowWidth;
    int             m_iWindowHeight;

    SDL_Surface*    m_pSurface;
};